<template>
  <div class="dialog-search">
      <el-form :inline="true" ref="ruleForm" :model="formInline" label-width="120px"
          class="demo-form-inline top-screen">
          <div class="top-screen-left">
              <div v-show="!isUnfold" class="packUp">
                  <div class="label" :ref="'label' + item.type + index" v-show="item.isShow"
                      v-for="(item, index) in itemList" :key="index"
                      @click.stop="showElFormItem('formItem' + item.type + index, 'label' + item.type + index)">
                      {{ item.label }}
                      <i class="el-icon-caret-bottom"></i>
                  </div>
              </div>
              <div class="searchForm" :class="isUnfold ? 'searchForm' : 'closeSearchForm'">
                  <el-form-item class="elFormItem" v-show="item.isShow" v-for="(item, index) in itemList"
                      :label="item.label + '：'" :key="index">
                      <div class="formItem" :style="isUnfold ? {} : { width: 'auto' }"
                          :ref="'formItem' + item.type + index">
                          <!-- 下拉选择框 -->
                          <el-select filterable v-if="item.type == 'select'" v-model="formInline[item.param]"
                              :multiple="item.multiple" :collapse-tags="item.collapseTags"
                              :placeholder="'请选择' + item.label" size="mini" clearable
                              @clear="() => clear(formInline[item.param], item.param)"
                              @change="() => { getMultipleInfo(item, formInline[item.param]); !isShowDefault && onSubmit() }">
                              <el-option v-for="(item2, index2) in item.selectOptions" :key="index2"
                                  :label="item2.text" :value="item2.value"></el-option>
                          </el-select>
                          <div class="selectOption" :data-custom="item.param" ref="selectOption"
                              v-if="item.type == 'select' && isUnfold">
                              <div class="optionList" ref="optionList">
                                  <span class="chooseItem" v-if="!item.multiple"
                                      :style="{ opacity: index2 < optionsNum[item.param] ? 1 : 0 }"
                                      :class="formInline[item.param] == item2.value ? 'activeItem' : ''"
                                      :title="index2 < optionsNum[item.param] ? item2.text : ''"
                                      v-for="(item2, index2) in item.selectOptions" :key="index2"
                                      @click="chooseselectOption(item, item2.value, item.multiple)">
                                      {{ item2.text }}</span>
                                  <span class="chooseItem" v-if="item.multiple"
                                      :style="{ opacity: index2 < optionsNum[item.param] ? 1 : 0 }"
                                      :class="multipleObj[item.param] && multipleObj[item.param].indexOf(item2.value) !== -1 ? 'activeItem' : ''"
                                      :title="index2 < optionsNum[item.param] ? item2.text : ''"
                                      v-for="(item2, index2) in item.selectOptions" :key="index2"
                                      @click="chooseselectOption(item, item2.value, item.multiple)">
                                      {{ item2.text }}</span>
                              </div>
                          </div>
                          <div v-if="item.type == 'select' && resetMoreBtn" class="successText moreBtn"
                              v-show="showMoreBtn[item.param]" @click="chooseMoreItem(item, item.selectOptions)">更多<i
                                  class="el-icon-d-arrow-right"></i> </div>
                          <!-- 下拉选择框end -->
                          <!-- 输入框 -->
                          <el-input class="elInput" v-if="item.type == 'input'" v-model="formInline[item.param]"
                              size="mini" :placeholder="'请输入' + item.label"
                              @clear="() => clear(formInline[item.param], item.param)" clearable
                              @change="() => { !isShowDefault && onSubmit() }"></el-input>
                          <!-- 输入框 -->
                          <!-- 日期范围选择框 -->
                          <!-- <el-date-picker
                              v-if="item.type == 'daterange' || item.type == 'datetimerange' || item.type == 'date' || item.type == 'datetime'"
                              v-model="formInline[item.param]" :value-format="item.valueFormat || 'yyyy-MM-dd'"
                              :format="item.format || 'yyyy-MM-dd'" clearable :type="item.type || ''"
                              :range-separator="item.rangeSeparator || '至'" :start-placeholder="item.startPlaceholder"
                              :end-placeholder="item.endPlaceholder" :placeholder="'请选择' + item.label"
                              :startPlaceholder="item.label + '开始日期'" :endPlaceholder="item.label + '结束日期'"
                              size="mini" :picker-options="pickerOptions[item.type]"
                              @clear="() => clear(formInline[item.param], item.param)"
                              @change="() => { !isShowDefault && onSubmit() }">
                          </el-date-picker> -->
                          <el-date-picker
                              v-if="item.type == 'daterange' || item.type == 'datetimerange' || item.type == 'date' || item.type == 'datetime'"
                              v-model="formInline[item.param]" :value-format="item.valueFormat || 'yyyy-MM-dd'"
                              :format="item.format || 'yyyy-MM-dd'" clearable :type="item.type || ''"
                              :range-separator="item.rangeSeparator || '至'" :start-placeholder="item.startPlaceholder"
                              :end-placeholder="item.endPlaceholder" :placeholder="'请选择' + item.label"
                              :startPlaceholder="item.label + '开始日期'" :endPlaceholder="item.label + '结束日期'"
                              size="mini" @clear="() => clear(formInline[item.param], item.param)"
                              @change="() => { !isShowDefault && onSubmit() }">
                          </el-date-picker>
                          <el-date-picker v-if="item.type == 'year'" :type="item.type || ''"
                              v-model="formInline[item.param]" :value-format="item.valueFormat || 'yyyy'"
                              :format="item.format || 'yyyy'" @clear="() => clear(formInline[item.param], item.param)"
                              @change="() => { !isShowDefault && onSubmit() }" placeholder="选择年">
                          </el-date-picker>
                          <!-- 日期范围选择框end -->
                          <!-- 级联选择器 -->
                          <el-cascader v-if="item.type == 'cascader'" v-model="formInline[item.param]" size="mini"
                              :value-format="item.valueFormat || 'yyyy'" :format="item.format || 'yyyy'"
                              :options="item.options" :props="item.props" :placeholder="'请选择' + item.label" clearable
                              @clear="() => clear(formInline[item.param], item.param)"
                              @change="() => { !isShowDefault && onSubmit() }"></el-cascader>
                          <!-- 级联选择器end -->
                      </div>
                  </el-form-item>
              </div>
              <slot name="formItem"></slot>
          </div>
          <div class="top-screen-right">
              <el-form-item v-if="isShowDefault">
                  <el-button type="" size="mini" @click="resetForm('ruleForm')"
                      class="top-right-bottom top-right-Reset-bottom top-right-bottom-I">重置</el-button>
                  <el-button type="primary" size="mini" @click="onSubmit"
                      class="top-right-bottom top-right-bottom-I">查询</el-button>
              </el-form-item>

              <i class="elIcon el-icon-setting" @click.stop="dialogVisible = true"></i>
              <i class="elIcon el-icon-refresh-right" :title="'重置'" @click.stop="retsetFormInline"></i>
              <i class="elIcon el-icon-arrow-down" v-if="this.isUnfold" @click.stop="packUp"></i>
              <i class="elIcon el-icon-arrow-up" v-else @click.stop="packUp"></i>
              <!-- 可用于显示其他按钮 -->
              <slot name="formButton" :item="formInline"></slot>
          </div>
      </el-form>
      <el-dialog title="查看更多" :visible.sync="dialogVisibleOptions" width="60%" :before-close="handleClose">
          <div class="searchOption">
              <span class="label">搜 索</span>
              <el-input class="input" v-model="inputSearchOption" placeholder="请输入内容"></el-input>
          </div>
          <div class="dialogOption">
              <!-- 单选 -->
              <span class="chooseItem" v-if="item2.text.indexOf(inputSearchOption) !== -1 && !chooseItem.multiple"
                  :class="formInline[chooseItem.param] == item2.value ? 'activeItem' : ''"
                  v-for="(item2, index2) in optionList" :key="index2"
                  @click="chooseselectOption(chooseItem, item2.value, chooseItem.multiple)">
                  {{ item2.text }}
              </span>
              <!-- 多选 -->
              <span class="chooseItem" v-if="item2.text.indexOf(inputSearchOption) !== -1 && chooseItem.multiple"
                  :class="multipleObj[chooseItem.param] && multipleObj[chooseItem.param].indexOf(item2.value) !== -1 ? 'activeItem' : ''"
                  v-for="(item2, index2) in optionList" :key="index2"
                  @click="chooseselectOption(chooseItem, item2.value, chooseItem.multiple)">
                  {{ item2.text }}
              </span>
          </div>
          <span slot="footer" class="dialog-footer">
              <el-button @click="dialogVisibleOptions = false">取 消</el-button>
              <el-button type="primary" @click="dialogVisibleOptions = false">确 定</el-button>
          </span>
      </el-dialog>
      <Draggable title="自定义筛选项字段" :dialogVisible="dialogVisible" :list="list" :keyName="routerName"
          @getDraggableList="getDraggableList" @closeDialog="closeDialog"></Draggable>
  </div>
</template>
<script>
import Draggable from '../Draggable';
export default {
  name: 'BaseSearch',
  props: {
      emitSearch: {
          // 是否立即执行搜索
          type: Boolean,
          default: false
      },
      isShowDefault: {
          //是否展示默认按钮
          default: false
      },
      unfoldFlag: {
          //是否展示默认按钮
          default: true
      },
      formItemList: {
          type: Array,
          default() {
              return [
                  {
                      label: '下拉框',
                      type: 'select',
                      selectOptions: [{ text: 111, value: 111 }],
                      param: 'company',
                      defaultSelect: '',
                      multiple: false
                  },
                  {
                      label: '输入框',
                      type: 'input',
                      param: 'name'
                  },
                  {
                      label: '日期范围',
                      type: 'datetimerange',
                      param: 'createtime'
                  },
                  {
                      label: '级联选择器',
                      type: 'cascader',
                      param: 'cascader',
                      options: [],
                      props: { multiple: false }
                  }
              ];
          }
      }
  },
  components: { Draggable },
  data() {
      let formInline = {};
      for (const obj of this.formItemList) {
          formInline[obj.param] = obj.defaultSelect || null;
      }
      return {
          refLabel: [],
          showOptionsNum: 3,
          inputSearchOption: "",
          optionList: [],
          resetMoreBtn: false,
          showMoreBtn: {},
          optionsNum: {},
          chooseItem: {},
          dialogVisibleOptions: false,
          list: JSON.parse(JSON.stringify(this.formItemList)),
          draggableList: [],
          dialogVisible: false,
          formInline: formInline,
          itemList: this.formItemList,
          isUnfold: this.unfoldFlag, //是否展开
          isSHow: false,
          routerName: this.$route.name + '_search',
          multipleObj: {},
          pickerOptions: {
              datetime: {
                  disabledDate(time) {
                      return time.getTime() > Date.now();
                  },
                  shortcuts: [{
                      text: '今天',
                      onClick(picker) {
                          picker.$emit('pick', new Date());
                      }
                  }, {
                      text: '昨天',
                      onClick(picker) {
                          const date = new Date();
                          date.setTime(date.getTime() - 3600 * 1000 * 24);
                          picker.$emit('pick', date);
                      }
                  }, {
                      text: '一周前',
                      onClick(picker) {
                          const date = new Date();
                          date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
                          picker.$emit('pick', date);
                      }
                  }]
              },
              date: {
                  disabledDate(time) {
                      return time.getTime() > Date.now();
                  },
                  shortcuts: [{
                      text: '今天',
                      onClick(picker) {
                          picker.$emit('pick', new Date());
                      }
                  }, {
                      text: '昨天',
                      onClick(picker) {
                          const date = new Date();
                          date.setTime(date.getTime() - 3600 * 1000 * 24);
                          picker.$emit('pick', date);
                      }
                  }, {
                      text: '一周前',
                      onClick(picker) {
                          const date = new Date();
                          date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
                          picker.$emit('pick', date);
                      }
                  }]
              },
              daterange: {
                  disabledDate(time) {
                      return time.getTime() > Date.now();
                  },
                  shortcuts: [{
                      text: '最近一周',
                      onClick(picker) {
                          const end = new Date();
                          const start = new Date();
                          start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
                          picker.$emit('pick', [start, end]);
                      }
                  }, {
                      text: '最近一个月',
                      onClick(picker) {
                          const end = new Date();
                          const start = new Date();
                          start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
                          picker.$emit('pick', [start, end]);
                      }
                  }, {
                      text: '最近三个月',
                      onClick(picker) {
                          const end = new Date();
                          const start = new Date();
                          start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
                          picker.$emit('pick', [start, end]);
                      }
                  }]
              },
              datetimerange: {
                  disabledDate(time) {
                      return time.getTime() > Date.now();
                  },
                  shortcuts: [{
                      text: '最近一周',
                      onClick(picker) {
                          const end = new Date();
                          const start = new Date();
                          start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
                          picker.$emit('pick', [start, end]);
                      }
                  }, {
                      text: '最近一个月',
                      onClick(picker) {
                          const end = new Date();
                          const start = new Date();
                          start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
                          picker.$emit('pick', [start, end]);
                      }
                  }, {
                      text: '最近三个月',
                      onClick(picker) {
                          const end = new Date();
                          const start = new Date();
                          start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
                          picker.$emit('pick', [start, end]);
                      }
                  }]
              }
          },
      };
  },
  watch: {
      emitSearch(newVal, oldVal) {
          // 是否立即触发搜索  用在弹窗中异步请求下拉框后  或者给下拉框赋值默认值后  需要用到这个方法
          if (newVal) {
              console.log('此时触发--立即执行搜索');
              this.$emit('search', this.formInline);
          }
      },
      itemList: {
          handler(newVal, oldVal) {
              for (const obj of this.formItemList) {
                  if (obj.defaultSelect) {
                      this.formInline[obj.param] = obj.defaultSelect;
                  }
              }
              this.getSelectChange();
          },
          deep: true
      }
  },
  mounted() {
      this.getList()
  },
  methods: {
      showElFormItem(refElFormItem, refLabel) {
          if (this.refLabel == refLabel) {
              this.refLabel = ''
              this.resetDomStyle();
          } else {
              this.refLabel = refLabel
              let label = this.$refs[refLabel][0];
              let labelRect = label.getBoundingClientRect();
              let labelLeft = labelRect.left;
              let labelTop = labelRect.top;
              let elFormItem = this.$refs[refElFormItem][0];
              this.resetDomStyle();
              elFormItem.style.position = 'fixed';
              elFormItem.style.top = labelTop + 40 + 'px';
              elFormItem.style.left = labelLeft - 15 + 'px';
              elFormItem.style.padding = 15 + 'px';
              elFormItem.style.backgroundColor = '#ffffff';
              elFormItem.style.zIndex = 1000;
              elFormItem.style.boxShadow = '0px 15px 10px rgba(0, 0, 0, 0.1)';
          }
          // const elFormItemRect = elFormItem.getBoundingClientRect();
          // const elFormItemLeft = elFormItemRect.left;
      },
      resetDomStyle() {
          let domList = document.querySelectorAll('.formItem')
          Array.from(domList).forEach(dom => {
              dom.style.position = 'static';
              dom.style.top = 'none';
              dom.style.left = 'none';
              dom.style.padding = '0';
              dom.style.backgroundColor = 'none';
              dom.style.boxShadow = 'none';
          })
      },
      //获取select  Options的数量  通过最大的展示宽度计算最多展示多少个option
      getSelectChange() {
          this.resetMoreBtn = false;
          this.$nextTick(() => {
              let selectList = this.$refs.selectOption || [];
              let optionDomList = this.$refs.optionList;
              this.showMoreBtn = {}
              this.optionsNum = {}
              selectList.forEach((item, index) => {
                  let pWidth = item.offsetWidth;
                  let cWidth = optionDomList[index].offsetWidth;
                  let childlist = optionDomList[index].children
                  let key = item.getAttribute('data-custom');
                  console.log(this.accumulateAndCount(Array.from(childlist), pWidth))
                  this.$set(this.showMoreBtn, key, pWidth < cWidth);
                  this.$set(this.optionsNum, key, this.accumulateAndCount(Array.from(childlist), pWidth));
              })
              this.resetMoreBtn = true;
          })
      },
      accumulateAndCount(arr, maxValue) {
          let sum = 0;
          let count = 0;
          for (let i = 0; i < arr.length; i++) {
              sum += arr[i].offsetWidth;
              count++;
              if (sum > maxValue) {
                  return count - 1; // 返回累加值小于等于5时的元素数量  
              }
          }
          return count; // 如果所有元素的累加值都小于等于5，则返回数组长度  
      },
      chooseMoreItem(item, options) {
          this.inputSearchOption = '';
          this.chooseItem = item;
          this.optionList = options || [];
          this.dialogVisibleOptions = true;
      },
      getMultipleInfo(item, options) {
          item.multiple && (this.multipleObj[item.param] = options || [])
      },
      chooseselectOption(item, value, multiple) {
          if (multiple) {
              if (!this.multipleObj[item.param]) {
                  this.multipleObj[item.param] = []
              }
              let index = this.multipleObj[item.param].indexOf(value)
              if (index !== -1) {
                  this.multipleObj[item.param].splice(index, 1)
              } else {
                  this.multipleObj[item.param].push(value)
              }
              this.$set(this.formInline, [item.param], this.multipleObj[item.param])
          } else {
              if (this.formInline[item.param] && this.formInline[item.param] == value) {
                  this.$set(this.formInline, [item.param], null);
              } else {
                  this.$set(this.formInline, [item.param], value);
              }
          }

          //触发搜索项
          this.$emit('search', this.formInline);
      },
      retsetFormInline() {
          for (let key in this.formInline) {
              this.formInline[key] = ''
          }
          for (let key in this.multipleObj) {
              this.multipleObj[key] = []
          }
          this.$emit('search', this.formInline);
      },
      getList() {
          let hasList = sessionStorage.getItem(this.routerName);
          if (hasList && JSON.parse(hasList)) {
              this.itemList = JSON.parse(hasList)
          } else {
              this.itemList = JSON.parse(JSON.stringify(this.formItemList))
          }
      },
      closeDialog() {
          this.dialogVisible = false
      },
      getDraggableList(list = this.formItemList) {
          this.itemList = list;
      },
      packUp() {
          this.isUnfold = !this.isUnfold
          this.$emit('isUnfold', this.isUnfold)
          this.getSelectChange();
          this.resetDomStyle();
      },
      clear(e, param) {
          if (e === '') {
              this.formInline[param] = null
          }
      },
      onSubmit() {
          this.formInline
          let searchData = {};
          for (let key in this.formInline) {
              searchData[key] = this.formInline[key] || null;
          }
          this.$emit('search', searchData);
      },
      handleClose(done) {
          this.$confirm('确认关闭？')
              .then(_ => {
                  done();
              })
              .catch(_ => { });
      },
      resetForm(formName) {
          this.$refs[formName].resetFields();
          let formInline = {};
          for (const obj of this.itemList) {
              // formInline[obj.param] = obj.defaultSelect || "";  // 重置时下拉框的默认值如果要保留就选用这个
              formInline[obj.param] = null; // 所有筛选条件清空
          }
          this.formInline = formInline;
          this.$emit('search', this.formInline);
      }
  }
};
</script>

<style lang="scss" scoped>
.searchOption {
  display: flex;
  align-items: center;
  margin-bottom: 20px;

  .label {
      width: 60px;
      text-align: right;
      font-weight: bold;
      margin-right: 15px;
  }

  .input {
      width: 300px;
  }

}

.ellipsis {
  white-space: nowrap;
  /* 防止文本换行 */
  overflow: hidden;
  /* 隐藏超出容器的内容 */
  text-overflow: ellipsis;
  /* 使用省略号表示被裁剪的文本 */
}

.dialog-search {
  padding: 0;
}

.el-form-item {
  display: block;
  margin-bottom: 10px;
  margin-right: 20px;
}

.demo-form-inline {
  display: flex;
  justify-content: space-between;
}

.top-screen-left {
  width: calc(100% - 120px);

  .packUp {
      font-size: 14px;
      font-weight: bold;
      color: #999999;
      line-height: 39px;
      height: 39px;
      display: flex;

      .label {
          margin-right: 20px;
          cursor: pointer;
      }
  }

  .packUp>.label:hover {
      color: #666666;
  }
}

.el-icon-setting,
.el-icon-arrow-down,
.el-icon-arrow-up {
  cursor: pointer;
}



.el-icon-caret-bottom {
  color: #0099ff;
}

.draggable {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  line-height: 30px;
}

.checkbox {
  width: 15px;
  height: 15px;
  border: 1px solid #cecece;
  padding: 3px;
  box-sizing: border-box;
  margin-right: 20px;
}

.top-screen-right {
  width: 120px;
  line-height: 29px;
  color: #409EFF;
  text-align: right;
}

.dialog-search {
  cursor: pointer;
}

.elIcon {
  font-size: 16px;
  padding: 10px;
  margin-left: 2px;

  &:hover {
      background-color: #40a6ff;
      color: #ffffff;
      border-radius: 6px;
  }
}

::v-deep .el-form-item__content {
  width: calc(100% - 200px);
}

.formItem {
  width: 100%;
  display: flex;
  flex-wrap: nowrap;
  justify-content: flex-start;

  .selectOption {
      width: calc(100% - 260px);
      margin-left: 5px;
      overflow: hidden;

      .optionList {
          display: flex;
          float: left;
      }

      .chooseItem {
          max-width: 140px;
          white-space: nowrap;
          /* 防止文本换行 */
          overflow: hidden;
          /* 隐藏超出容器的内容 */
          text-overflow: ellipsis;
          /* 使用省略号表示被裁剪的文本 */
          padding: 0 20px;
          color: #999999;
          display: inline-block;
          border-radius: 4px;

          &:hover {
              color: #40a6ff;
          }
      }

      .activeItem {
          color: #40a6ff;
          font-weight: bold;
      }
  }

}

.dialogOption {
  display: flex;
  justify-content: flex-start;
  flex-wrap: wrap;
  max-height: 370px;
  overflow-y: auto;

  .chooseItem {
      padding: 5px 20px;
      margin: 5px;
      background-color: #0000000a;
      border-radius: 4px;

      &:hover {
          background-color: #40a6ff90;
          color: #666666;
      }
  }

  .activeItem {
      background-color: #40a6ff;
      color: #ffffff;
  }
}

.moreBtn {
  width: 50px;
  height: 28px;
  margin-left: 15px;
  display: inline-block;
  line-height: 28px;
}

.elInput {
  max-width: 180px;
}

.closeSearchForm {
  height: 0;
  overflow: hidden;
}
</style>